package mskruch.gps.calculation;

import gpstools.TrainingPoint;
import mskruch.gps.Point;
import mskruch.gps.PointFactory;

/**
 * Hear Rate calculator
 * 
 * @author Marcin Skruch
 * @author Slawomir.Przednowek
 * 
 */
public class DefaultHeartRateCalculator implements HeartRateCalculator {
    /** time in ms */
    private long time = 0;
    /** time * hr sum */
    private double sum = 0;
    /** maximum heart rate */
    private short max = 0;
    /** minimum heart rate */
    private short min = 0;

    /** most recent added point */
    private Point last = null;

    DefaultHeartRateCalculator() {
    }

    /**
     * add a point to calculation
     * 
     * @param point
     *            gps point
     */
    @Override
    public HeartRateCalculator add(final Point point) {
        if (point.getHeartRate() == null) {
            return this; /* ignore points with no HR data */
        }

        if (last != null) {
            if (point.getTime() < last.getTime()) {
            	return this;
            }
            final double localTime = point.getTime() - last.getTime();
            final short hr = last.getHeartRate();
            sum += localTime * (hr + last.getHeartRate()) / 2.0;

            time += localTime;
            if (hr < min) {
                min = hr;
            } else if (hr > max) {
                max = hr;
            }
        } else {
            /* first point */
            min = max = point.getHeartRate();
        }
        last = point;
        return this;
    }
    
    @Override
    public void add(TrainingPoint point) {
        add(PointFactory.newPoint(point));
    }

    /* (non-Javadoc)
     * @see mskruch.gps.calculation.HeartRateCalculator#getAverage()
     */
    @Override
    public Short getAverage() {
        if (time == 0 && last == null) {
            /* no data */
            return null;
        } else if (time == 0) {
            /* only one point */
            return last.getHeartRate();
        } else {
            /* many points */
            return (short) Math.round(sum / time);
        }
    }

    /* (non-Javadoc)
     * @see mskruch.gps.calculation.HeartRateCalculator#getMinimum()
     */
    @Override
    public Short getMinimum() {
        if (last == null) {
            /* no data */
            return null;
        } else {
            return min;
        }
    }

    /* (non-Javadoc)
     * @see mskruch.gps.calculation.HeartRateCalculator#getMaximum()
     */
    @Override
    public Short getMaximum() {
        if (last == null) {
            /* no data */
            return null;
        } else {
            return max;
        }
    }

}
